﻿using System;
using System.Diagnostics.Contracts;
using System.Web.Script.Serialization;
using System.Web.UI;

namespace OpenWaves.Web.Controls
{
    [Serializable]
    [ParseChildren(true)]
    public class GoogleMapViewport
    {
        #region Support for databinding view poert properties
        [NonSerialized]
        private EventHandler dataBinding;
        public event EventHandler DataBinding
        {
            add { this.dataBinding += value; }
            remove { this.dataBinding -= value; }
        }

        [NonSerialized]
        private object bindingContainer;
        [ScriptIgnore]
        public object BindingContainer
        {
            get { return this.bindingContainer; }
            set { this.bindingContainer = value; }
        }
        #endregion

        public GoogleMapViewport()
        {
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public GoogleMapViewport( GeoPoint center, int zoom)
        {
            Contract.Requires<ArgumentNullException>(center != null);
            Contract.Requires<ArgumentOutOfRangeException>(zoom >=0);

            Zoom = zoom;
            Center = center;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public GoogleMapViewport(GeoRectangle bounds)
        {
            Contract.Requires<ArgumentNullException>(bounds != null);

            Bounds = bounds;
        }

        public static GoogleMapViewport FromCenterAndZoom(GeoPoint center, int zoom)
        {
            return new GoogleMapViewport(center, zoom);
        }

        public static GoogleMapViewport FromBounds(GeoPoint topLeft, GeoPoint bottomRight)
        {
            return new GoogleMapViewport(new GeoRectangle(topLeft, bottomRight));
        }

        public void DataBind()
        {
            if (this.dataBinding != null)
                this.dataBinding(this, EventArgs.Empty);
        }

        private int zoom = -1;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public int Zoom
        {
            get { return this.zoom; }
            set { this.zoom = value; }
        }

        private GeoPoint center;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public GeoPoint Center
        {
            get { return this.center; }
            set { this.center = value; }
        }

        private GeoRectangle bounds;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public GeoRectangle Bounds
        {
            get { return this.bounds; }
            set { this.bounds = value; }
        }

        [ContractInvariantMethod]
        private void ContractInvariantMethod()
        {
            var nothingSet = this.Zoom == -1 && this.Center == null && this.Bounds == null;
            var centerOrZoomSet = this.Zoom >= 0 || this.Center != null;
            var boundsSet = this.Bounds != null;

            //
            // Don't allow both center and bounds based viewports
            //
            Contract.Invariant(nothingSet || (centerOrZoomSet ^ boundsSet));
        }
    }
}